package sunlight.ws.axis2.clients;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;

public class ResourceLockingClient {
	
	public static EndpointReference targetEPR = 
        new EndpointReference("http://localhost:8080/axis2/services/ResourceLockingService");
	
	private Options 	 options;
	private ServiceClient sender;
	
	private String resourceID;
	
	private OMElement unlockResourcePayload;
	private OMElement lockResourcePayload;
	private OMElement isResourceLockedPayload;
	private OMElement updateResourceTimerPayload;
	
	public ResourceLockingClient(String resourceID, int timeout) throws AxisFault{
		super();
		
		options = new Options();
	    options.setTo(targetEPR);
	    options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
	    options.setCallTransportCleanup(true); 
	    
	    sender = new ServiceClient();
	    sender.setOptions(options);
	    
	    this.resourceID = resourceID;
	    
	    //---Initializeaza metodele ------------//
	    unlockResourcePayload  		= unlockResourcePayload(this.resourceID);
	    lockResourcePayload    		= lockResourcePayload(this.resourceID, timeout);
	    isResourceLockedPayload 	= isResourceLockedPayload(this.resourceID);
	    updateResourceTimerPayload  = updateResourceTimerPayload(this.resourceID, timeout);
	}
	
	public void lock() throws AxisFault, ResourceAlreadyLockedException{
		
		//------~ Verifica daca resursa nu este deja blocata ~------//
		boolean alreadyLocked = this.isLocked(); 
		 
		 if(alreadyLocked){//resursa este deja blocata de alt utilizator;
			 throw new ResourceAlreadyLockedException();
		 }
		 else{//blocheaza noua resursa;
		     sender.fireAndForget(lockResourcePayload);
		 }
	}
	
	public void unlock() throws AxisFault{
		sender.fireAndForget(unlockResourcePayload);
	}
	

	public boolean isLocked() throws AxisFault{
		OMElement result = sender.sendReceive(isResourceLockedPayload);
		String response  = result.getFirstElement().getText();
		
		if(response.equals("true")){
			return true;
		}
		 
		return false;
	}
	
	
	public void updateTimeout() throws AxisFault{
		sender.fireAndForget(updateResourceTimerPayload);
	}
	
	
	public void closeClient() throws AxisFault{
		this.sender.cleanup();
		this.sender.cleanupTransport();
	}
	
	public static OMElement lockResourcePayload(String rname, int seconds) {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace("http://adrian.sunlight.ws.axis2/xsd", "tns");

        OMElement method = fac.createOMElement("lockResource", omNs);
        
        OMElement value1 = fac.createOMElement("rname", omNs);
        value1.addChild(fac.createOMText(value1, rname));
        method.addChild(value1);
        
        OMElement value2 = fac.createOMElement("seconds", omNs);
        value2.addChild(fac.createOMText(value2, String.valueOf(seconds)));
        method.addChild(value2);
        
        return method;
    }

    public static OMElement unlockResourcePayload(String rname) {
        OMFactory fac 	 = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace("http://adrian.sunlight.ws.axis2/xsd", "tns");

        OMElement method = fac.createOMElement("unlockResource", omNs);

        OMElement value = fac.createOMElement("rname", omNs);
        value.addChild(fac.createOMText(value, rname));
        method.addChild(value);
        
        return method;
    }
    
    public static OMElement isResourceLockedPayload(String rname) {
    	 OMFactory fac = OMAbstractFactory.getOMFactory();
	     OMNamespace omNs = fac.createOMNamespace("http://adrian.sunlight.ws.axis2/xsd", "tns");

	     OMElement method = fac.createOMElement("isResourceLocked", omNs);

	     OMElement value = fac.createOMElement("rname", omNs);
	     value.addChild(fac.createOMText(value, rname));
	     method.addChild(value);
	        
	     return method;
    }
    
    public static OMElement updateResourceTimerPayload(String rname, int timeout) {
    	 OMFactory fac = OMAbstractFactory.getOMFactory();
	     OMNamespace omNs = fac.createOMNamespace("http://adrian.sunlight.ws.axis2/xsd", "tns");

	     OMElement method = fac.createOMElement("updateResourceTimer", omNs);

	     OMElement value1 = fac.createOMElement("rname", omNs);
	     value1.addChild(fac.createOMText(value1, rname));
	     method.addChild(value1);
	     
	     OMElement value2 = fac.createOMElement("seconds", omNs);
	     value2.addChild(fac.createOMText(value2, String.valueOf(timeout)));
	     method.addChild(value2);
	        
	     return method;
   }
}
